- Main Page
- Related Pages
- Files

# register.c

    00001 /*
    00002  * $Id: register.c,v 1.36 2008/01/06 22:38:19 joerg_wunsch Exp $
    00003  *
    00004  ****************************************************************************
    00005  *
    00006  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
    00007  * Copyright (C) 2001, 2002, 2003, 2004  Theodore A. Roth
    00008  *
    00009  * This program is free software; you can redistribute it and/or modify
    00010  * it under the terms of the GNU General Public License as published by
    00011  * the Free Software Foundation; either version 2 of the License, or
    00012  * (at your option) any later version.
    00013  *
    00014  * This program is distributed in the hope that it will be useful,
    00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00017  * GNU General Public License for more details.
    00018  *
    00019  * You should have received a copy of the GNU General Public License
    00020  * along with this program; if not, write to the Free Software
    00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00022  *
    00023  ****************************************************************************
    00024  */
    00025
    00026 #include <config.h>
    00027
    00028 #include <stdio.h>
    00029 #include <stdlib.h>
    00030
    00031 #include "avrerror.h"
    00032 #include "avrmalloc.h"
    00033 #include "avrclass.h"
    00034 #include "utils.h"
    00035 #include "callback.h"
    00036 #include "op_names.h"
    00037
    00038 #include "storage.h"
    00039 #include "flash.h"
    00040
    00041 #include "vdevs.h"
    00042 #include "memory.h"
    00043 #include "stack.h"
    00044 #include "register.h"
    00045 #include "sram.h"
    00046 #include "eeprom.h"
    00047 #include "timers.h"
    00048 #include "ports.h"
    00049
    00050 #include "avrcore.h"
    00051
    00052 #include "display.h"
    00053 #include "intvects.h"
    00054
    00055 /****************************************************************************\
    00056  *
    00057  * Status Register Methods.
    00058  *
    00059 \****************************************************************************/
    00060
    00061 static uint8_t sreg_read (VDevice *dev, int addr);
    00062 static void sreg_write (VDevice *dev, int addr, uint8_t val);
    00063 static void sreg_reset (VDevice *dev);
    00064 static void sreg_add_addr (VDevice *dev, int addr, char *name, int rel_addr,
    00065                            void *data);
    00066
    00067 VDevice *
    00068 sreg_create (int addr, char *name, int rel_addr, void *data)
    00069 {
    00070     return (VDevice *)sreg_new ();
    00071 }
    00072
    00073 SREG *
    00074 sreg_new (void)
    00075 {
    00076     SREG *sreg;
    00077
    00078     sreg = avr_new (SREG, 1);
    00079     sreg_construct (sreg);
    00080     class_overload_destroy ((AvrClass *)sreg, sreg_destroy);
    00081
    00082     return sreg;
    00083 }
    00084
    00085 void
    00086 sreg_construct (SREG *sreg)
    00087 {
    00088     if (sreg == NULL)
    00089         avr_error ("passed null ptr");
    00090
    00091     vdev_construct ((VDevice *)sreg, sreg_read, sreg_write, sreg_reset,
    00092                     sreg_add_addr);
    00093
    00094     sreg->sreg.reg = 0;
    00095 }
    00096
    00097 void
    00098 sreg_destroy (void *sreg)
    00099 {
    00100     if (sreg == NULL)
    00101         return;
    00102
    00103     vdev_destroy (sreg);
    00104 }
    00105
    00106 extern uint8_t sreg_get (SREG *sreg);
    00107
    00108 extern void sreg_set (SREG *sreg, uint8_t val);
    00109
    00110 extern uint8_t sreg_get_bit (SREG *sreg, int bit);
    00111
    00112 extern void sreg_set_bit (SREG *sreg, int bit, int val);
    00113
    00114 static uint8_t
    00115 sreg_read (VDevice *dev, int addr)
    00116 {
    00117     return sreg_get ((SREG *)dev);
    00118 }
    00119
    00120 static void
    00121 sreg_write (VDevice *dev, int addr, uint8_t val)
    00122 {
    00123     sreg_set ((SREG *)dev, val);
    00124 }
    00125
    00126 static void
    00127 sreg_reset (VDevice *dev)
    00128 {
    00129     display_io_reg (SREG_IO_REG, 0);
    00130     ((SREG *)dev)->sreg.reg = 0;
    00131 }
    00132
    00133 static void
    00134 sreg_add_addr (VDevice *dev, int addr, char *name, int rel_addr, void *data)
    00135 {
    00136     /* Nothing to do here. */
    00137 }
    00138
    00139
    00140 /****************************************************************************\
    00141  *
    00142  * General Purpose Working Register (gpwr) Methods.
    00143  *
    00144 \****************************************************************************/
    00145
    00146 static uint8_t gpwr_read (VDevice *dev, int addr);
    00147 static void gpwr_write (VDevice *dev, int addr, uint8_t val);
    00148 static void gpwr_reset (VDevice *dev);
    00149
    00150 GPWR *
    00151 gpwr_new (void)
    00152 {
    00153     GPWR *gpwr;
    00154
    00155     gpwr = avr_new (GPWR, 1);
    00156     gpwr_construct (gpwr);
    00157     class_overload_destroy ((AvrClass *)gpwr, gpwr_destroy);
    00158
    00159     return gpwr;
    00160 }
    00161
    00162 void
    00163 gpwr_construct (GPWR *gpwr)
    00164 {
    00165     if (gpwr == NULL)
    00166         avr_error ("passed null ptr");
    00167
    00168     vdev_construct ((VDevice *)gpwr, gpwr_read, gpwr_write, gpwr_reset, NULL);
    00169
    00170     gpwr_reset ((VDevice *)gpwr);
    00171 }
    00172
    00173 void
    00174 gpwr_destroy (void *gpwr)
    00175 {
    00176     if (gpwr == NULL)
    00177         return;
    00178
    00179     vdev_destroy (gpwr);
    00180 }
    00181
    00182 extern uint8_t gpwr_get (GPWR *gpwr, int reg);
    00183
    00184 extern void gpwr_set (GPWR *gpwr, int reg, uint8_t val);
    00185
    00186 static uint8_t
    00187 gpwr_read (VDevice *dev, int addr)
    00188 {
    00189     return gpwr_get ((GPWR *)dev, addr);
    00190 }
    00191
    00192 static void
    00193 gpwr_write (VDevice *dev, int addr, uint8_t val)
    00194 {
    00195     gpwr_set ((GPWR *)dev, addr, val);
    00196 }
    00197
    00198 static void
    00199 gpwr_reset (VDevice *dev)
    00200 {
    00201     int i;
    00202
    00203     for (i = 0; i < GPWR_SIZE; i++)
    00204         gpwr_set ((GPWR *)dev, i, 0);
    00205 }
    00206
    00207 /****************************************************************************\
    00208  *
    00209  * ACSR(VDevice) : Analog Comparator Control and Status Register Definition
    00210  *
    00211 \****************************************************************************/
    00212
    00213 static uint8_t acsr_read (VDevice *dev, int addr);
    00214 static void acsr_write (VDevice *dev, int addr, uint8_t val);
    00215 static void acsr_reset (VDevice *dev);
    00216
    00217 ACSR *
    00218 acsr_new (uint8_t func_mask)
    00219 {
    00220     ACSR *acsr;
    00221
    00222     acsr = avr_new (ACSR, 1);
    00223     acsr_construct (acsr, func_mask);
    00224     class_overload_destroy ((AvrClass *)acsr, acsr_destroy);
    00225
    00226     return acsr;
    00227 }
    00228
    00229 void
    00230 acsr_construct (ACSR *acsr, uint8_t func_mask)
    00231 {
    00232     if (acsr == NULL)
    00233         avr_error ("passed null ptr");
    00234
    00235     vdev_construct ((VDevice *)acsr, acsr_read, acsr_write, acsr_reset,
    00236                     vdev_def_AddAddr);
    00237
    00238     acsr->func_mask = func_mask;
    00239     acsr->acsr = 0;
    00240 }
    00241
    00242 void
    00243 acsr_destroy (void *acsr)
    00244 {
    00245     if (acsr == NULL)
    00246         return;
    00247
    00248     vdev_destroy (acsr);
    00249 }
    00250
    00251 int
    00252 acsr_get_bit (ACSR *acsr, int bit)
    00253 {
    00254     return !!(acsr->acsr & acsr->func_mask & (1 << bit));
    00255 }
    00256
    00257 void
    00258 acsr_set_bit (ACSR *acsr, int bit, int val)
    00259 {
    00260     /* the ACO bit is read only */
    00261     acsr->acsr =
    00262         set_bit_in_byte (acsr->acsr, bit,
    00263                          val) & acsr->func_mask & ~(mask_ACO);
    00264 }
    00265
    00266 static uint8_t
    00267 acsr_read (VDevice *dev, int addr)
    00268 {
    00269     ACSR *reg = (ACSR *)dev;
    00270
    00271     return (reg->acsr & reg->func_mask);
    00272 }
    00273
    00274 static void
    00275 acsr_write (VDevice *dev, int addr, uint8_t val)
    00276 {
    00277     ACSR *reg = (ACSR *)dev;
    00278
    00279     /* the ACO bit is read only */
    00280     reg->acsr = (val & reg->func_mask & ~(mask_ACO));
    00281 }
    00282
    00283 static void
    00284 acsr_reset (VDevice *dev)
    00285 {
    00286     ((ACSR *)dev)->acsr = 0;
    00287 }
    00288
    00289 /****************************************************************************\
    00290  *
    00291  * MCUCR(VDevice) : MCU general control register
    00292  *
    00293 \****************************************************************************/
    00294
    00295 static uint8_t mcucr_read (VDevice *dev, int addr);
    00296 static void mcucr_write (VDevice *dev, int addr, uint8_t val);
    00297 static void mcucr_reset (VDevice *dev);
    00298
    00299 MCUCR *
    00300 mcucr_new (uint8_t func_mask)
    00301 {
    00302     MCUCR *mcucr;
    00303
    00304     mcucr = avr_new (MCUCR, 1);
    00305     mcucr_construct (mcucr, func_mask);
    00306     class_overload_destroy ((AvrClass *)mcucr, mcucr_destroy);
    00307
    00308     return mcucr;
    00309 }
    00310
    00311 void
    00312 mcucr_construct (MCUCR *mcucr, uint8_t func_mask)
    00313 {
    00314     if (mcucr == NULL)
    00315         avr_error ("passed null ptr");
    00316
    00317     vdev_construct ((VDevice *)mcucr, mcucr_read, mcucr_write, mcucr_reset,
    00318                     vdev_def_AddAddr);
    00319
    00320     mcucr->func_mask = func_mask;
    00321     mcucr->mcucr = 0;
    00322 }
    00323
    00324 void
    00325 mcucr_destroy (void *mcucr)
    00326 {
    00327     if (mcucr == NULL)
    00328         return;
    00329
    00330     vdev_destroy (mcucr);
    00331 }
    00332
    00333 int
    00334 mcucr_get_bit (MCUCR *reg, int bit)
    00335 {
    00336     return !!(reg->mcucr & reg->func_mask & (1 << bit));
    00337 }
    00338
    00339 void
    00340 mcucr_set_bit (MCUCR *reg, int bit, int val)
    00341 {
    00342     reg->mcucr = set_bit_in_byte (reg->mcucr, bit, val) & reg->func_mask;
    00343 }
    00344
    00345 static uint8_t
    00346 mcucr_read (VDevice *dev, int addr)
    00347 {
    00348     MCUCR *reg = (MCUCR *)dev;
    00349
    00350     return (reg->mcucr & reg->func_mask);
    00351 }
    00352
    00353 static void
    00354 mcucr_write (VDevice *dev, int addr, uint8_t val)
    00355 {
    00356     MCUCR *reg = (MCUCR *)dev;
    00357
    00358     reg->mcucr = (val & reg->func_mask);
    00359 }
    00360
    00361 static void
    00362 mcucr_reset (VDevice *dev)
    00363 {
    00364     ((MCUCR *)dev)->mcucr = 0;
    00365 }
    00366
    00367 /****************************************************************************\
    00368  *
    00369  * WDTCR(VDevice) : Watchdog timer control register
    00370  *
    00371 \****************************************************************************/
    00372
    00373 /*  static int    wdtcr_get_bit   ( WDTCR *wdtcr, int bit ); */
    00374 static void wdtcr_set_bit (WDTCR *wdtcr, int bit, int val);
    00375
    00376 static uint8_t wdtcr_read (VDevice *dev, int addr);
    00377 static void wdtcr_write (VDevice *dev, int addr, uint8_t val);
    00378 static void wdtcr_reset (VDevice *dev);
    00379
    00380 static int wdtcr_timer_cb (uint64_t time, AvrClass *data);
    00381 static int wdtcr_toe_clr_cb (uint64_t time, AvrClass *data);
    00382
    00383 WDTCR *
    00384 wdtcr_new (uint8_t func_mask)
    00385 {
    00386     WDTCR *wdtcr;
    00387
    00388     wdtcr = avr_new (WDTCR, 1);
    00389     wdtcr_construct (wdtcr, func_mask);
    00390     class_overload_destroy ((AvrClass *)wdtcr, wdtcr_destroy);
    00391
    00392     return wdtcr;
    00393 }
    00394
    00395 void
    00396 wdtcr_construct (WDTCR *wdtcr, uint8_t func_mask)
    00397 {
    00398     if (wdtcr == NULL)
    00399         avr_error ("passed null ptr");
    00400
    00401     vdev_construct ((VDevice *)wdtcr, wdtcr_read, wdtcr_write, wdtcr_reset,
    00402                     vdev_def_AddAddr);
    00403
    00404     wdtcr->func_mask = func_mask;
    00405
    00406     wdtcr_reset ((VDevice *)wdtcr);
    00407 }
    00408
    00409 void
    00410 wdtcr_destroy (void *wdtcr)
    00411 {
    00412     if (wdtcr == NULL)
    00413         return;
    00414
    00415     vdev_destroy (wdtcr);
    00416 }
    00417
    00418 /*
    00419  * Function wdtcr_update: Called when the WDR instruction is issued
    00420  */
    00421 void
    00422 wdtcr_update (WDTCR *wdtcr)
    00423 {
    00424     wdtcr->last_WDR = get_program_time ();
    00425 }
    00426
    00427 #if 0                           /* This doesn't seem to be used anywhere. */
    00428 static int
    00429 wdtcr_get_bit (WDTCR *reg, int bit)
    00430 {
    00431     return !!(reg->wdtcr & reg->func_mask & (1 << bit));
    00432 }
    00433 #endif
    00434
    00435 static void
    00436 wdtcr_set_bit (WDTCR *reg, int bit, int val)
    00437 {
    00438     reg->wdtcr = set_bit_in_byte (reg->wdtcr, bit, val) & reg->func_mask;
    00439 }
    00440
    00441 static uint8_t
    00442 wdtcr_read (VDevice *dev, int addr)
    00443 {
    00444     WDTCR *reg = (WDTCR *)dev;
    00445
    00446     return (reg->wdtcr & reg->func_mask);
    00447 }
    00448
    00449 /*
    00450  * FIXME: Should the wdtcr->toe_clk counter be reset to TOE_CLKS
    00451  * every time a WDTOE is set 1? I.E. does the hw reset the 4 cycle
    00452  * counter every time WDTOE is set? This code assumes it does.
    00453  */
    00454 static void
    00455 wdtcr_write (VDevice *dev, int addr, uint8_t val)
    00456 {
    00457     WDTCR *reg = (WDTCR *)dev;
    00458     uint8_t wd_enabled = (reg->wdtcr & mask_WDE);
    00459
    00460     CallBack *cb;
    00461
    00462     if (reg->func_mask & mask_WDTOE)
    00463     {                           /* Device has WDTOE functionality */
    00464
    00465         if ((reg->wdtcr & mask_WDE) && !(reg->wdtcr & mask_WDTOE))
    00466         {
    00467             /* WDE can _NOT_ be cleared if WDTOE is zero */
    00468             val |= mask_WDE;
    00469         }
    00470
    00471         if (val & mask_WDTOE)
    00472         {                       /* program has set WDTOE */
    00473             reg->toe_clk = TOE_CLKS;
    00474
    00475             /* create and install the callback if it not already installed */
    00476             if (reg->toe_cb == NULL)
    00477             {
    00478                 cb = callback_new (wdtcr_toe_clr_cb, (AvrClass *)reg);
    00479                 reg->toe_cb = cb;
    00480                 avr_core_clk_cb_add ((AvrCore *)vdev_get_core (dev), cb);
    00481             }
    00482         }
    00483     }
    00484
    00485     reg->wdtcr = (val & reg->func_mask);
    00486
    00487     if ((wd_enabled == 0) && (val & mask_WDE) && (reg->timer_cb == NULL))
    00488     {
    00489         /* install the WD timer callback */
    00490         cb = callback_new (wdtcr_timer_cb, (AvrClass *)reg);
    00491         reg->timer_cb = cb;
    00492         avr_core_async_cb_add ((AvrCore *)vdev_get_core (dev), cb);
    00493     }
    00494
    00495     if (wd_enabled && ((val & mask_WDE) == 0) && (reg->timer_cb != NULL))
    00496     {
    00497         /* tell callback to remove itself */
    00498         reg->timer_cb = NULL;
    00499     }
    00500 }
    00501
    00502 static void
    00503 wdtcr_reset (VDevice *dev)
    00504 {
    00505     WDTCR *wdtcr = (WDTCR *)dev;
    00506
    00507     wdtcr->wdtcr = 0;
    00508
    00509     wdtcr->last_WDR = get_program_time (); /* FIXME: This might not be the
    00510                                               right thing to do */
    00511     wdtcr->timer_cb = NULL;
    00512
    00513     wdtcr->toe_clk = TOE_CLKS;
    00514     wdtcr->toe_cb = NULL;
    00515 }
    00516
    00517 /*
    00518  * Timer callback will remove itself if wdtcr->timer_cb is set NULL.
    00519  */
    00520 static int
    00521 wdtcr_timer_cb (uint64_t time, AvrClass *data)
    00522 {
    00523     WDTCR *wdtcr = (WDTCR *)data;
    00524     uint64_t time_diff;
    00525     uint64_t time_out;
    00526
    00527     if (wdtcr->timer_cb == NULL)
    00528         return CB_RET_REMOVE;
    00529
    00530     time_diff = time - wdtcr->last_WDR;
    00531     time_out = TIMEOUT_BASE * (1 << (wdtcr->wdtcr & mask_WDP));
    00532
    00533     if (time_diff > time_out)
    00534     {
    00535         avr_warning ("watchdog reset: time %lld\n", time_diff);
    00536
    00537         /* reset the device, we timed out */
    00538         avr_core_irq_raise ((AvrCore *)vdev_get_core ((VDevice *)wdtcr),
    00539                             irq_vect_table_index (RESET));
    00540     }
    00541
    00542     return CB_RET_RETAIN;
    00543 }
    00544
    00545 /*
    00546  * The WDTOE is cleared by hardware after TOE_CLKS clock cycles.
    00547  */
    00548 static int
    00549 wdtcr_toe_clr_cb (uint64_t time, AvrClass *data)
    00550 {
    00551     WDTCR *wdtcr = (WDTCR *)data;
    00552
    00553     if (wdtcr->toe_cb == NULL)
    00554         return CB_RET_REMOVE;
    00555
    00556     if (wdtcr->toe_clk > 0)
    00557     {
    00558         wdtcr->toe_clk--;
    00559     }
    00560     else
    00561     {
    00562         wdtcr_set_bit (wdtcr, bit_WDTOE, 0);
    00563         wdtcr->toe_cb = NULL;   /* So we know that cb is not installed */
    00564         return CB_RET_REMOVE;
    00565     }
    00566
    00567     return CB_RET_RETAIN;
    00568 }
    00569
    00570 /****************************************************************************\
    00571  *
    00572  * RAMPZ(VDevice) : The RAMPZ register used by ELPM and ESPM instructions.
    00573  *
    00574  * Even though the rampz register is not available to all devices, we will
    00575  * install it for all in the simulator. It just so much easier that way and
    00576  * we're already assuming that the compiler generated the correct code in
    00577  * many places anyways. Let's see if we get bit.
    00578  *
    00579 \****************************************************************************/
    00580
    00581 static uint8_t rampz_read (VDevice *dev, int addr);
    00582 static void rampz_write (VDevice *dev, int addr, uint8_t val);
    00583 static void rampz_reset (VDevice *dev);
    00584
    00585 VDevice *
    00586 rampz_create (int addr, char *name, int rel_addr, void *data)
    00587 {
    00588     return (VDevice *)rampz_new ();
    00589 }
    00590
    00591 RAMPZ *
    00592 rampz_new (void)
    00593 {
    00594     RAMPZ *rampz;
    00595
    00596     rampz = avr_new (RAMPZ, 1);
    00597     rampz_construct (rampz);
    00598     class_overload_destroy ((AvrClass *)rampz, rampz_destroy);
    00599
    00600     return rampz;
    00601 }
    00602
    00603 void
    00604 rampz_construct (RAMPZ *rampz)
    00605 {
    00606     if (rampz == NULL)
    00607         avr_error ("passed null ptr");
    00608
    00609     vdev_construct ((VDevice *)rampz, rampz_read, rampz_write, rampz_reset,
    00610                     vdev_def_AddAddr);
    00611
    00612     rampz->reg = 0;
    00613 }
    00614
    00615 void
    00616 rampz_destroy (void *rampz)
    00617 {
    00618     if (rampz == NULL)
    00619         return;
    00620
    00621     vdev_destroy (rampz);
    00622 }
    00623
    00624 uint8_t
    00625 rampz_get (RAMPZ *rampz)
    00626 {
    00627     return rampz->reg;
    00628 }
    00629
    00630 void
    00631 rampz_set (RAMPZ *rampz, uint8_t val)
    00632 {
    00633     rampz->reg = val;
    00634 }
    00635
    00636 static uint8_t
    00637 rampz_read (VDevice *dev, int addr)
    00638 {
    00639     return rampz_get ((RAMPZ *)dev);
    00640 }
    00641
    00642 static void
    00643 rampz_write (VDevice *dev, int addr, uint8_t val)
    00644 {
    00645     rampz_set ((RAMPZ *)dev, val);
    00646 }
    00647
    00648 static void
    00649 rampz_reset (VDevice *dev)
    00650 {
    00651     display_io_reg (RAMPZ_IO_REG, 0);
    00652     ((RAMPZ *)dev)->reg = 0;
    00653 }

Automatically generated by Doxygen 1.5.5 on 7 Nov 2008.